package com.newmedia.gui;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.util.Vector;


import javax.swing.ImageIcon;
import javax.swing.JPanel;

import com.newmedia.main.Main;

@SuppressWarnings("serial")
public

//Handles the selection of different keys, as well as drawing of axises.
class GraphicMusic extends JPanel{
	
	public static final int LINE_1 = 1;
	public static final int LINE_2 = 2;
	public static final int LINE_3 = 2;
	public static final int LINE_4 = 2;
	
	private int line = 1;
	
	static int sizeHeight = 500;
	static int sizeWidth = 600;
	static int scale = 30;
	static int scaleX = 30;
	static Main.mKey keyChoice;
	
	Vector<Vector<Integer>> lineXs = new Vector<Vector<Integer>>();
	Vector<Vector<Integer>> lineYs = new Vector<Vector<Integer>>();
	Vector<Vector<Notes>> lineNotes = new Vector<Vector<Notes>>();

	String actionMessage="";
	int x=15, k;
	private static final Stroke LINE_STROKE = new BasicStroke(2f);
	private static final AlphaComposite OVER_HALF = 
        AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); 
       
   
	//add background image
	private static final long serialVersionUID = 1L;
	Image bg = new ImageIcon(getClass().getResource("paper.jpg")).getImage(); 
         
        private Key m_Key;
	
	public char[] mAlphabet = {'A', 'B', 'C', 'D', 'E', 'F', 'G' };
	
	public GraphicMusic(Main.mKey key) {
		keyChoice = key;
		setScale();
		addMouse();       
        
	}
	
	
	// Used to draw graph
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		// Add background image to the graphic panel
		g.drawImage(bg, 0, 0, getWidth(), getHeight(), this);
		
		// Make graph
		g.drawLine(30,15,30,sizeHeight - scale * 2);
		g.drawLine(30, sizeHeight - scale * 2, sizeWidth , sizeHeight - scale * 2);
		
		//Make grid
		int p = 30; 
		while(p < 900){
			g.drawLine(30+p, 15, 30+p, sizeHeight - scale * 2);
				p = p + 30;}
				
	    int q = 45;
		while(q <= sizeHeight-45){
			g.drawLine(30, sizeHeight - q, sizeWidth, sizeHeight - q);
			q = q + 45;
		}
		
		//Draw moving horizontal transparent red bar
		Graphics2D q1 =(Graphics2D) g;
		q1.setStroke(LINE_STROKE);
		q1.setComposite(OVER_HALF); 
	    q1.setColor(Color.red);
	    q1.drawLine(x, 0, x, 600);
     	for( k=0;k<=30;k+=2){
     		q1.drawLine(x+k, 0, x+k, 600);
	    }
     	    	
     	//Make the note on the panel blue
     	q1.setPaint(new GradientPaint(
                new Point2D.Double(),
                Color.blue, 
                new Point2D.Double(), 
                Color.blue));
		
		m_Key = new Key(keyChoice, g);
		m_Key.indexKey();
		m_Key.drawLabels();
		
		for(int k = 0; k < lineXs.size(); k++){
			//Dots be drawn here.
			int[] xs = new int[lineXs.get(k).size()];
			int[] ys = new int[lineYs.get(k).size()];
			
			if(lineNotes.size() == line-1) lineNotes.add(new Vector<Notes>());
			//notes = new Vector<Notes>();
			int noteIndex = 0;
			int savedIndex = 0;
			if(lineNotes.size() == k) lineNotes.add(new Vector<Notes>());
			else lineNotes.set(k, new Vector<Notes>());
			for(int j = 0; j < lineXs.get(k).size(); ++j) {
			
				// Add dots
				boolean raised= true;
				switch(k){
				case 0: g.setColor(Color.getHSBColor(0f, 1f, 1f)); break;
				case 1: g.setColor(Color.getHSBColor(0.198f, 1f, 1f)); break;
				case 2: g.setColor(Color.getHSBColor(0.334f, 1f, 1f)); break;
				case 3: g.setColor(Color.getHSBColor(0.667f, 1f, 1f)); break;
				}
				g.fill3DRect(lineXs.get(k).elementAt(j) - 5, lineYs.get(k).elementAt(j) - 5, 10, 10, raised);
				
				// Make arrays for the graph line
				xs[j] = lineXs.get(k).elementAt(j);
				ys[j] = lineYs.get(k).elementAt(j);
				
				Notes n = new Notes(xs[j], ys[j], m_Key);
				
				// If first one add one note with length 1
				if( lineNotes.get(k).size() == 0 ) {
					lineNotes.get(k).addElement(n);
					noteIndex++;
				}
				// If the new note is different, add new note with length one, finish adding length to old note
				else if(lineNotes.get(k).elementAt(noteIndex-1).getNote() != n.getNote() ) {
					lineNotes.get(k).addElement(n);
					System.out.println(savedIndex + " " + j);
					if(lineXs.get(k).elementAt(savedIndex) + 30 != lineXs.get(k).elementAt(j)) {
						lineNotes.get(k).elementAt(noteIndex-1).addToLength(lineXs.get(k).elementAt(savedIndex), lineXs.get(k).elementAt(j) - 30);
					}
					noteIndex++;
					savedIndex = j;
				}
				// If next note is same, compute difference
				else {
					System.out.println(lineXs.get(k).elementAt(j - 1) + " " + lineXs.get(k).elementAt(j));
					lineNotes.get(k).elementAt(noteIndex-1).addToLength(lineXs.get(k).elementAt(j - 1), lineXs.get(k).elementAt(j));
					savedIndex = j;
					System.out.println(savedIndex + " " + j);
				}
			}
			for(int j = 0; j < lineNotes.get(k).size(); ++j) {
				System.out.print(lineNotes.get(k).elementAt(j).getNote() + " " + lineNotes.get(k).elementAt(j).getLength() + " ");
				
			}
			System.out.println();
			
			// Make line on graph
			g.drawPolyline(xs, ys, lineXs.get(k).size());
		}
	}
		
	public void addMouse(){
		// Read in the mouse listener for reading in notes
		addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				int x = e.getX();
				int y = e.getY();
				
				// Round up or down the y to make sure always a note
				int round = y % scale;
				if (round > scale/2) {
					y = y + (scale - round + 5);
				}
				else {
					y = y - round + 5;
				}
				
				// If below last note, move up to last note
				if( y >= sizeHeight - scale * 2) {
					y = sizeHeight - scale * 3;
				}
				
				// If above first note, move down to first note
				if( y < scale + 5) {
					y = scale + 5;
				}
				
				// Round left or right the x to make sure always on a beat
				round = x % scaleX;
				if (round > scaleX/2) {
					x = x + (scaleX - round);
				}
				else {
					x = x - round;
				}			
				
				// Makes sure the points don't backtrack and won't be off the graph
				if( x > 30 && ( lineXs.size () == line-1 || x > lineXs.get(line-1).lastElement() ) ) {
					if(lineXs.size() == line-1) lineXs.add(new Vector<Integer>());
					if(lineYs.size() == line-1) lineYs.add(new Vector<Integer>());
					lineXs.get(line-1).addElement( new Integer(x) );
					lineYs.get(line-1).addElement( new Integer(y) );
				}
				

				validate();
				repaint();
			}
		});
	}
		
	public int getScale(){
		return scale;
	}
	
	public int getWidth(){
		return sizeWidth;
	}
	
	public int getHeight(){
		return sizeHeight;
	}
	
	public String[] getKey(){
		return m_Key.getKey();
	}
	
	public void setKey(Main.mKey k){
		keyChoice = k;
	}
	
	public void setScale(){
		if(keyChoice == Main.mKey.ALL) {
			scale = 30;
		}
		else {
			scale = 45;
		}
	}
	
	public Vector<Vector<Notes>> getNotes(){
		return lineNotes;
	}
	
	public void setLine(int l){
		line = l;
	}
}








	